package com.jaywalkable.vkeyboard;

import java.util.Hashtable;
import java.util.TreeMap;

import com.jaywalkable.vkeyboard.impl.BengaliVKeyboardLayout;
import com.jaywalkable.vkeyboard.impl.SimpleVTextComponent;
import com.jaywalkable.vkeyboard.util.StringLengthComparator;

class VKeyboardImpl implements VKeyboard {

    private final StringBuilder sb = new StringBuilder();
    private Character lastDecodedChar = null;
    private String dictWord = new String();
    private int replaceCount = 0;
    private VKeyboardKeyConverter converter;
    private VTextComponent vTextComponent;
    private Hashtable<String, String> dictionary;
    private VKeyboardLayout keyboardLayout;

    public VKeyboardImpl(VTextComponent vTextComponent) {
        this.vTextComponent = vTextComponent;
    }

    VKeyboardImpl() {
        // TODO Auto-generated constructor stub
    }

    public void setConverter(VKeyboardKeyConverter decoder) {
        this.converter = decoder;
        reset();
    }

    private void reset() {
        replaceCount = 0;
        sb.setLength(0);
    }

    public void setVTextComponent(VTextComponent vTextComponent) {
        this.vTextComponent = vTextComponent;
        reset();
    }

    @Override
    public final void keyPressed(Character ch) {
        String str = sb.append(ch).toString();
        Character[] decoded = converter.convert(str);
        ifcond: if (decoded == null) {
            reset();
            str = String.valueOf(ch);

            if (keyboardLayout instanceof BengaliVKeyboardLayout) {
                BengaliVKeyboardLayout bengaliVKeyboardLayout = (BengaliVKeyboardLayout) keyboardLayout;
                Character[] chars = converter.convert(str);
                if (chars != null && chars.length == 1) {
                    String tCh = bengaliVKeyboardLayout.transformVowel(lastDecodedChar, chars[chars.length - 1]);
                    if (tCh != null) {
                        str += tCh;
                    }
                }
            }
            sb.append(str);
            decoded = converter.convert(str);
            if (decoded == null) {
                decoded = new Character[] { ch };
                vTextComponent.keyTyped(0, decoded);
                replaceCount = decoded.length;
                lastDecodedChar = null;
            } else {
                break ifcond;
            }
            return;
        } else {
            if (decoded.length == 1 && keyboardLayout instanceof BengaliVKeyboardLayout) {
                BengaliVKeyboardLayout bengaliVKeyboardLayout = (BengaliVKeyboardLayout) keyboardLayout;
                String tCh = bengaliVKeyboardLayout.transformVowel(lastDecodedChar, decoded[0]);
                if (tCh != null) {
                    decoded = converter.convert(str + tCh);
                }

            }
        }

        vTextComponent.keyTyped(replaceCount, decoded);
        boolean hasMultpleRules = converter.foundMultiplePrefixMatch();
        if (hasMultpleRules) {
            replaceCount = decoded.length;
        } else {
            reset();
        }
        lastDecodedChar = decoded.length == 0 ? null : decoded[decoded.length - 1];
    }

    private void filterDictionary(Character ch) {
        String word = dictWord + ch;
        if (isDictionaryWord(word)) {
            dictWord = word;
        }
    }

    public void setDictionary(Hashtable<String, String> dictionary) {
        this.dictionary = dictionary;
        TreeMap<String, Character[]> map = new TreeMap<String, Character[]>(new StringLengthComparator());

        for (String key : dictionary.keySet()) {
            SimpleVTextComponent vTextComponent = new SimpleVTextComponent();
            VKeyboard keyboard = new VKeyboardImpl(vTextComponent);
            keyboard.setConverter(converter);
            String value = dictionary.get(key);
            for (int i = 0; i < value.length(); i++) {
                keyboard.keyPressed(value.charAt(i));
            }
            String output = vTextComponent.getText();

            Character[] chars = new Character[output.length()];
            for (int i = 0; i < chars.length; i++) {
                chars[i] = output.charAt(i);
            }
            map.put(key, chars);
        }
        map.putAll(converter.getKeyMap());
        this.converter = new VKeyboardKeyConverterImpl(map);
    }

    private boolean isDictionaryWord(String word) {
        for (String key : dictionary.keySet()) {
            if (key.startsWith(word)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void setKeyboardLayout(VKeyboardLayout keyboardLayout) {
        this.keyboardLayout = keyboardLayout;
    }

}
